#pragma once
#include<string>
#include<cstring>
#include<functional>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include"LogMessage.hpp"

#define CHARNUM 1024
#define default_ip "0.0.0.0"

using namespace std;

typedef function<void*(int, string, uint16_t, string)> Fun;

class server
{
public:
    server(Fun fun, uint16_t port): _sock_fd(-1), _port(port), 
    _fun(fun), _ip(default_ip){}

    ~server(){}

    void init(){

        //创建套接字
        _sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sock_fd < 0){ logmessage(FATAL, "create socket error"); exit(0);}
        else { logmessage(NORMAL, "create socket success"); }

        //绑定端口
        struct sockaddr_in bind_addr;
        bzero(&bind_addr, sizeof(bind_addr));
        bind_addr.sin_family = AF_INET;
        bind_addr.sin_port = htons(_port);
        bind_addr.sin_addr.s_addr = inet_addr(_ip.c_str());
        
        int check = bind(_sock_fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr));
        if (check == -1){ logmessage(FATAL, "bind socket error"); exit(0);}
        else { logmessage(NORMAL, "bind socket success"); }

    }

    void start()
    {
        char buff[CHARNUM] = {0};
        struct sockaddr_in client;
        bzero(&client, sizeof(client));
        socklen_t len = sizeof(client);

        while(true)
        {
            size_t size = recvfrom(_sock_fd, buff, sizeof(buff)-1, 0, (struct sockaddr*)&client, &len);
            if (size > 0)
            {
                buff[size] = '\0';
                string client_ip = inet_ntoa(client.sin_addr);
                uint16_t client_port = ntohs(client.sin_port);

                _fun(_sock_fd, client_ip, client_port, buff);
            }
        }
    }
private:
    string _ip;
    uint16_t _port;
    int _sock_fd;
    Fun _fun;
};